#!/usr/bin/env python
# coding=utf-8
import os
import sys
import shutil
import argparse
import importlib.util
import webbrowser
import socketserver
import asyncio
from http.server import SimpleHTTPRequestHandler
from datetime import datetime


parser = argparse.ArgumentParser(
    description='parallel distributed runner for robot framework')
parser.add_argument('--suite', nargs='?', type=str,
                    help='specify suite, default current work directory')
parser.add_argument('--local', nargs='?', type=bool,
                    help='please set local')
parser.add_argument('--env', nargs='?', type=str,
                    help='please set env')
args = parser.parse_args()

if args.suite:
    suite_path = 'suites/{}.robot'.format(args.suite)
else:
    suite_path = 'suites'
suite = args.suite
os.environ['SUITE'] = str(suite)
if args.local:
    os.environ['LOCAL'] = 'false'
else:
    os.environ['LOCAL'] = 'true'
if not args.env:
    os.environ['ENV'] = 'test'
else:
    os.environ['ENV'] = args.env

from database_lib.testdb.test_model import TestModel
from database_lib.testdb.test_data import TestData
from database_lib.testdb.api_statistics import ApiStatistics
from database_lib.testdb.api_collection import ApiCollection
from robot.run import run_cli
from comm_lib import const


class Run(object):
    # 初始化数据
    def __init__(self):
        file_path = os.path.dirname(__file__)
        self.report_path = os.path.join(file_path, 'reports')
        TestModel().create_all_db()
        TestData().delete_all_data()
        self.init_data()
        const.add_service()

    def setup(self):
        sys.path.append(os.path.abspath(os.path.curdir))
        shutil.rmtree(self.report_path, ignore_errors=True)
        os.mkdir(self.report_path)
        if not os.path.isdir(self.report_path):
            os.mkdir(self.report_path)

    async def serve(self):
        try:
            httpd = socketserver.TCPServer(
                ("", 9001), SimpleHTTPRequestHandler, bind_and_activate=False)
            await asyncio.sleep(0)
            httpd.allow_reuse_address = True
            httpd.server_bind()
            httpd.server_activate()
            httpd.serve_forever()
        except KeyboardInterrupt:
            pass

    async def open_browser(self):
        webbrowser.open('http://127.0.0.1:9001/reports/report.html')

    def teardown(self):
        loop = asyncio.get_event_loop()
        tasks = [asyncio.ensure_future(self.serve()), asyncio.ensure_future(self.open_browser())]
        loop.run_until_complete(asyncio.gather(*tasks))
        loop.close()

    @staticmethod
    def init_data():
        service = os.environ['SUITE']
        module_spec = importlib.util.find_spec(f'init_lib.{service.lower()}')
        if not module_spec:
            raise ImportError(f'Module {service} Not Found!')
        module = importlib.util.module_from_spec(module_spec)
        module_spec.loader.exec_module(module)
        service_name = ''.join(service[:1].upper() + service[1:])
        if hasattr(module, service_name):
            obj = getattr(module, service_name)()
            getattr(obj, 'main')()

    @staticmethod
    def statistics():
        service = os.environ['SUITE']
        time = datetime.now().date()
        api_statistics = ApiStatistics()
        statistics_count = api_statistics.select_statistics_by_service(service, time)
        collection = ApiCollection()
        api_count = int(collection.select_api_count_by_service(service))
        case_count = int(collection.select_case_count_by_service(service))
        if statistics_count:
            api_statistics.update_data_by_service(service, time, api_count, case_count)
        else:
            api_statistics.add_statistics(service, time, api_count, case_count)

    def main(self):
        args_list = [
                        '-r', f'{self.report_path}/report.html',
                        '-o', f'{self.report_path}/output.xml',
                        '-l', f'{self.report_path}/log.html',
                        '-L', 'TRACE'
                    ] + [suite_path]
        run_cli(args_list, False)
        if os.environ['LOCAL'] == 'true':
            self.teardown()
        else:
            self.statistics()


if __name__ == '__main__':
    Run().main()
